3ddb79c1yHLp08JhgPxIMcZ8DwN9hg xen-2.4.16/include/xeno/if.h
3ddb79c1RCWOkWPQRzbYVTX_e-E7CA xen-2.4.16/include/xeno/if_ether.h
3ddb79c2IYah7z7hkzPyOiG8szKkyw xen-2.4.16/include/xeno/if_packet.h
+3df0af1c-QrOEqpPHq4uL3NZzCeJCg xen-2.4.16/include/xeno/in.h
3ddb79c0GurNF9tDWqQbAwJFH8ugfA xen-2.4.16/include/xeno/init.h
3ddb79c1Vi5VleJAOKHAlY0G2zAsgw xen-2.4.16/include/xeno/interrupt.h
3ddb79c2J6EnruiygRhBCgftzMzTeQ xen-2.4.16/include/xeno/ioctl.h
akw27@boulderdash.cl.cam.ac.uk
+akw27@labyrinth.cl.cam.ac.uk
smh22@boulderdash.cl.cam.ac.uk
struct pfn_info *page = NULL;
net_ring_t *net_ring;
blk_ring_t *blk_ring;
+ net_vif_t *net_vif;
if ( strncmp(__va(mod[0].mod_start), "XenoGues", 8) )
{
/* Add virtual network interfaces and point to them in startinfo. */
while (params->num_vifs-- > 0) {
- net_ring = create_net_vif(dom);
+ net_vif = create_net_vif(dom);
+ net_ring = net_vif->net_ring;
if (!net_ring) panic("no network ring!\n");
}
virt_startinfo_address->net_rings = p->net_ring_base;
/* Create initial domain 0. */
dom0_params.num_vifs = 1;
dom0_params.memory_kb = opt_dom0_mem;
+ add_default_net_rule(0, opt_ipbase); // add vfr info for dom0
new_dom = do_newdomain();
if ( new_dom == NULL ) panic("Error creating domain 0\n");
#include <xeno/init.h>
#include <xeno/slab.h>
#include <xeno/spinlock.h>
+#include <xeno/if_ether.h>
+#include <linux/skbuff.h>
+#include <xeno/netdevice.h>
+#include <xeno/in.h>
/* vif globals
* sys_vif_list is a lookup table for vifs, used in packet forwarding.
kmem_cache_t *net_vif_cache;
kmem_cache_t *net_rule_cache;
static rwlock_t net_rule_lock = RW_LOCK_UNLOCKED;
+static rwlock_t sys_vif_lock = RW_LOCK_UNLOCKED;
-net_ring_t *create_net_vif(int domain)
+void print_net_rule_list();
+
+net_vif_t *create_net_vif(int domain)
{
net_vif_t *new_vif;
net_ring_t *new_ring;
{
return NULL;
}
- dom_task->net_vif_list[dom_task->num_net_vifs] = new_vif;
new_ring = dom_task->net_ring_base + dom_task->num_net_vifs;
memset(new_ring, 0, sizeof(net_ring_t));
- dom_task->net_vif_list[dom_task->num_net_vifs]->net_ring = new_ring;
- skb_queue_head_init(
- &dom_task->net_vif_list[dom_task->num_net_vifs]->skb_list);
- dom_task->net_vif_list[dom_task->num_net_vifs]->id = sys_vif_count++;
- dom_task->num_net_vifs++;
+ new_vif->net_ring = new_ring;
+ skb_queue_head_init(&new_vif->skb_list);
+ new_vif->domain = domain;
+
+ write_lock(&sys_vif_lock);
+ new_vif->id = sys_vif_count;
+ sys_vif_list[sys_vif_count++] = new_vif;
+ write_unlock(&sys_vif_lock);
- return new_ring;
+ dom_task->net_vif_list[dom_task->num_net_vifs] = new_vif;
+ dom_task->num_net_vifs++;
+
+ return new_vif;
}
/* delete the last vif in the given domain. There doesn't seem to be any reason
{
kfree_skb(skb);
}
+
+ write_lock(&sys_vif_lock);
+ sys_vif_list[p->net_vif_list[i]->id] = NULL; // system vif list not gc'ed
+ write_unlock(&sys_vif_lock);
+
kmem_cache_free(net_vif_cache, p->net_vif_list[i]);
}
+void print_vif_list()
+{
+ int i;
+ net_vif_t *v;
+
+ printk("Currently, there are %d VIFs.\n", sys_vif_count);
+ for (i=0; i<sys_vif_count; i++)
+ {
+ v = sys_vif_list[i];
+ printk("] VIF Entry %d(%d):\n", i, v->id);
+ printk(" > net_ring*: %p\n", v->net_ring);
+ printk(" > domain : %u\n", v->domain);
+ }
+}
int add_net_rule(net_rule_t *rule)
{
int delete_net_rule(net_rule_t *rule)
{
net_rule_ent_t *ent = net_rule_list, *prev = NULL;
-
- while ( (ent) && (!(memcmp(rule, &ent->r, sizeof(net_rule_t)))) )
+ while ( (ent) && ((memcmp(rule, &ent->r, sizeof(net_rule_t))) != 0) )
{
prev = ent;
ent = ent->next;
}
- if (ent)
+ if (ent != NULL)
{
write_lock(&net_rule_lock);
- if (prev)
+ if (prev != NULL)
{
prev->next = ent->next;
}
kmem_cache_free(net_rule_cache, ent);
write_unlock(&net_rule_lock);
}
-
return 0;
}
-
+
+/* add_default_net_rule.
+ * this is a utility function to route all traffic with the specified
+ * ip address to the specified vif. It's used to set up domain zero.
+ */
+void add_default_net_rule(int vif_id, u32 ipaddr)
+{
+ net_rule_t new_rule;
+
+ //outbound rule.
+ memset(&new_rule, 0, sizeof(net_rule_t));
+ new_rule.src_addr = ipaddr;
+ new_rule.src_addr_mask = 0xffffffff;
+ new_rule.src_interface = vif_id;
+ new_rule.dst_interface = VIF_PHYSICAL_INTERFACE;
+ new_rule.action = NETWORK_ACTION_ACCEPT;
+ new_rule.proto = NETWORK_PROTO_ANY;
+ add_net_rule(&new_rule);
+
+ //inbound rule;
+ memset(&new_rule, 0, sizeof(net_rule_t));
+ new_rule.dst_addr = ipaddr;
+ new_rule.dst_addr_mask = 0xffffffff;
+ new_rule.src_interface = VIF_PHYSICAL_INTERFACE;
+ new_rule.dst_interface = vif_id;
+ new_rule.action = NETWORK_ACTION_ACCEPT;
+ new_rule.proto = NETWORK_PROTO_ANY;
+ add_net_rule(&new_rule);
+
+}
+
void print_net_rule(net_rule_t *r)
{
printk("===] NET RULE:\n");
printk("=] dst_port : %u\n", r->dst_port);
printk("=] dst_port_mask : %u\n", r->dst_port_mask);
printk("=] dst_proto : %u\n", r->proto);
- printk("=] src_interface : %u\n", r->src_interface);
- printk("=] dst_interface : %u\n", r->dst_interface);
+ printk("=] src_interface : %d\n", r->src_interface);
+ printk("=] dst_interface : %d\n", r->dst_interface);
printk("=] action : %u\n", r->action);
}
printk("\nTotal of %d rules.\n", count);
}
+/* Apply the rules to this skbuff and return the vif id that it is bound for.
+ * -1 to drop.
+ */
+
+int net_find_rule(u8 nproto, u8 tproto, u32 src_addr, u32 dst_addr, u16 src_port, u16 dst_port,
+ int src_vif)
+{
+ net_rule_ent_t *ent;
+ int dest = VIF_DROP;
+
+ read_lock(&net_rule_lock);
+
+ ent = net_rule_list;
+
+ while (ent)
+ {
+ if ( ( (ent->r.src_interface == src_vif)
+ || (ent->r.src_interface == VIF_ANY_INTERFACE) )
+
+ && (!((ent->r.src_addr ^ src_addr) & ent->r.src_addr_mask ))
+ && (!((ent->r.dst_addr ^ dst_addr) & ent->r.dst_addr_mask ))
+ && (!((ent->r.src_port ^ src_port) & ent->r.src_port_mask ))
+ && (!((ent->r.dst_port ^ dst_port) & ent->r.dst_port_mask ))
+
+ && (
+ (ent->r.proto == NETWORK_PROTO_ANY)
+ || ((ent->r.proto == NETWORK_PROTO_IP) && (nproto == (u8)ETH_P_IP))
+ || ((ent->r.proto == NETWORK_PROTO_ARP) && (nproto == (u8)ETH_P_ARP))
+ || ((ent->r.proto == NETWORK_PROTO_TCP) && (tproto == IPPROTO_TCP))
+ || ((ent->r.proto == NETWORK_PROTO_UDP) && (tproto == IPPROTO_UDP))
+ )
+ )
+ {
+ break;
+ }
+ ent = ent->next;
+ }
+
+ if (ent) (dest = ent->r.dst_interface);
+ read_unlock(&net_rule_lock);
+ return dest;
+}
+
+int net_get_target_vif(struct sk_buff *skb)
+{
+ int target = VIF_DROP;
+ skb->h.raw = skb->nh.raw = skb->data;
+ if ( skb->len < 2 ) goto drop;
+ switch ( ntohs(skb->mac.ethernet->h_proto) )
+ {
+ case ETH_P_ARP:
+ if ( skb->len < 28 ) goto drop;
+ target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(skb->nh.raw + 14)),
+ ntohl(*(u32 *)(skb->nh.raw + 24)), 0, 0,
+ skb->src_vif);
+ break;
+ case ETH_P_IP:
+ if ( skb->len < 20 ) goto drop;
+ skb->h.raw += ((*(unsigned char *)(skb->nh.raw)) & 0x0f) * 4;
+ switch ( *(unsigned char *)(skb->nh.raw + 9) )
+ {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ target = net_find_rule((u8)ETH_P_IP, *(u8 *)(skb->nh.raw + 9),
+ ntohl(*(u32 *)(skb->nh.raw + 12)),
+ ntohl(*(u32 *)(skb->nh.raw + 16)),
+ ntohs(*(u16 *)(skb->h.raw)),
+ ntohs(*(u16 *)(skb->h.raw + 2)),
+ skb->src_vif);
+ break;
+ default: // ip-based protocol where we don't have ports.
+ target = net_find_rule((u8)ETH_P_IP, *(u8 *)(skb->nh.raw + 9),
+ ntohl(*(u32 *)(skb->nh.raw + 12)),
+ ntohl(*(u32 *)(skb->nh.raw + 16)),
+ 0,
+ 0,
+ skb->src_vif);
+ }
+ break;
+ }
+ skb->dst_vif=target;
+ return target;
+
+ drop:
+ return VIF_DROP;
+}
+
/*
* This is the hook function to handle guest-invoked traps requesting
* changes to the network system.
void __init net_init (void)
{
sys_vif_count = 0;
+ memset(sys_vif_list, 0, sizeof(sys_vif_list));
net_rule_list = NULL;
net_vif_cache = kmem_cache_create("net_vif_cache", sizeof(net_vif_t),
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
return ret;
}
+/* Event message note:
+ *
+ * Here, as in the interrupts to the guestos, additional network interfaces
+ * are defined. These definitions server as placeholders for the event bits,
+ * however, in the code these events will allways be referred to as shifted
+ * offsets from the base NET events.
+ */
+
/* Events that a guest OS may receive from the hypervisor. */
-#define EVENT_NET_TX 0x01 /* packets for transmission. */
-#define EVENT_NET_RX 0x02 /* empty buffers for receive. */
-#define EVENT_TIMER 0x04 /* a timeout has been updated. */
-#define EVENT_DIE 0x08 /* OS is about to be killed. Clean up please! */
-#define EVENT_BLK_TX 0x10 /* packets for transmission. */
-#define EVENT_BLK_RX 0x20 /* empty buffers for receive. */
+#define EVENT_BLK_TX 0x01 /* packets for transmission. */
+#define EVENT_BLK_RX 0x02 /* empty buffers for receive. */
+#define EVENT_TIMER 0x04 /* a timeout has been updated. */
+#define EVENT_DIE 0x08 /* OS is about to be killed. Clean up please! */
+#define EVENT_NET_TX 0x10 /* packets for transmission. */
+#define EVENT_NET_RX 0x20 /* empty buffers for receive. */
+#define EVENT_NET2_TX 0x40 /* packets for transmission. */
+#define EVENT_NET2_RX 0x80 /* empty buffers for receive. */
+
+/* should these macros and the ones below test for range violation? */
+#define EVENT_NET_TX_FOR_VIF(x) (EVENT_NET_TX << (2 * x))
+#define EVENT_NET_RX_FOR_VIF(x) (EVENT_NET_RX << (2 * x))
+
/* Bit offsets, as opposed to the above masks. */
-#define _EVENT_NET_TX 0
-#define _EVENT_NET_RX 1
-#define _EVENT_TIMER 2
-#define _EVENT_DIE 3
-#define _EVENT_BLK_TX 4
-#define _EVENT_BLK_RX 5
+#define _EVENT_BLK_TX 0
+#define _EVENT_BLK_RX 1
+#define _EVENT_TIMER 2
+#define _EVENT_DIE 3
+#define _EVENT_NET_TX 4
+#define _EVENT_NET_RX 5
+#define _EVENT_NET2_TX 6
+#define _EVENT_NET2_RX 7
+
+#define _EVENT_NET_TX_FOR_VIF(x) (_EVENT_NET_TX + (2 * x))
+#define _EVENT_NET_RX_FOR_VIF(x) (_EVENT_NET_RX + (2 * x))
/*
* NB. We expect that this struct is smaller than a page.
/*
* Hypervisor will only signal event delivery via the "callback
* exception" when this value is non-zero. Hypervisor clears this when
- * notiying the guest OS -- thsi prevents unbounded reentrancy and
+ * notiying the guest OS -- this prevents unbounded reentrancy and
* stack overflow (in this way, acts as an interrupt-enable flag).
*/
unsigned long events_enable;
} net_ring_t;
/* Specify base of per-domain array. Get returned free slot in the array. */
-net_ring_t *create_net_vif(int domain);
+//net_ring_t *create_net_vif(int domain);
/* Packet routing/filtering code follows:
*/
#define NETWORK_ACTION_ACCEPT 0
#define NETWORK_ACTION_COUNT 1
-#define NETWORK_PROTO_IP 0
-#define NETWORK_PROTO_TCP 1
-#define NETWORK_PROTO_UDP 2
-#define NETWORK_PROTO_ARP 3
+#define NETWORK_PROTO_ANY 0
+#define NETWORK_PROTO_IP 1
+#define NETWORK_PROTO_TCP 2
+#define NETWORK_PROTO_UDP 3
+#define NETWORK_PROTO_ARP 4
typedef struct net_rule_st
{
u16 dst_port_mask;
u16 proto;
- u16 src_interface;
- u16 dst_interface;
+ int src_interface;
+ int dst_interface;
u16 action;
} net_rule_t;
--- /dev/null
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions of the Internet Protocol.
+ *
+ * Version: @(#)in.h 1.0.1 04/21/93
+ *
+ * Authors: Original taken from the GNU Project <netinet/in.h> file.
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IN_H
+#define _LINUX_IN_H
+
+#include <linux/types.h>
+
+/* Standard well-defined IP protocols. */
+enum {
+ IPPROTO_IP = 0, /* Dummy protocol for TCP */
+ IPPROTO_ICMP = 1, /* Internet Control Message Protocol */
+ IPPROTO_IGMP = 2, /* Internet Group Management Protocol */
+ IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */
+ IPPROTO_TCP = 6, /* Transmission Control Protocol */
+ IPPROTO_EGP = 8, /* Exterior Gateway Protocol */
+ IPPROTO_PUP = 12, /* PUP protocol */
+ IPPROTO_UDP = 17, /* User Datagram Protocol */
+ IPPROTO_IDP = 22, /* XNS IDP protocol */
+ IPPROTO_RSVP = 46, /* RSVP protocol */
+ IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
+
+ IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */
+
+ IPPROTO_PIM = 103, /* Protocol Independent Multicast */
+
+ IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */
+ IPPROTO_AH = 51, /* Authentication Header protocol */
+ IPPROTO_COMP = 108, /* Compression Header protocol */
+
+ IPPROTO_RAW = 255, /* Raw IP packets */
+ IPPROTO_MAX
+};
+
+
+/* Internet address. */
+struct in_addr {
+ __u32 s_addr;
+};
+
+#define IP_TOS 1
+#define IP_TTL 2
+#define IP_HDRINCL 3
+#define IP_OPTIONS 4
+#define IP_ROUTER_ALERT 5
+#define IP_RECVOPTS 6
+#define IP_RETOPTS 7
+#define IP_PKTINFO 8
+#define IP_PKTOPTIONS 9
+#define IP_MTU_DISCOVER 10
+#define IP_RECVERR 11
+#define IP_RECVTTL 12
+#define IP_RECVTOS 13
+#define IP_MTU 14
+#define IP_FREEBIND 15
+
+/* BSD compatibility */
+#define IP_RECVRETOPTS IP_RETOPTS
+
+/* IP_MTU_DISCOVER values */
+#define IP_PMTUDISC_DONT 0 /* Never send DF frames */
+#define IP_PMTUDISC_WANT 1 /* Use per route hints */
+#define IP_PMTUDISC_DO 2 /* Always DF */
+
+#define IP_MULTICAST_IF 32
+#define IP_MULTICAST_TTL 33
+#define IP_MULTICAST_LOOP 34
+#define IP_ADD_MEMBERSHIP 35
+#define IP_DROP_MEMBERSHIP 36
+
+/* These need to appear somewhere around here */
+#define IP_DEFAULT_MULTICAST_TTL 1
+#define IP_DEFAULT_MULTICAST_LOOP 1
+
+/* Request struct for multicast socket ops */
+
+struct ip_mreq
+{
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+};
+
+struct ip_mreqn
+{
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_address; /* local IP address of interface */
+ int imr_ifindex; /* Interface index */
+};
+
+struct in_pktinfo
+{
+ int ipi_ifindex;
+ struct in_addr ipi_spec_dst;
+ struct in_addr ipi_addr;
+};
+
+/* Structure describing an Internet (IP) socket address. */
+#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
+struct sockaddr_in {
+ sa_family_t sin_family; /* Address family */
+ unsigned short int sin_port; /* Port number */
+ struct in_addr sin_addr; /* Internet address */
+
+ /* Pad to size of `struct sockaddr'. */
+ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
+ sizeof(unsigned short int) - sizeof(struct in_addr)];
+};
+#define sin_zero __pad /* for BSD UNIX comp. -FvK */
+
+
+/*
+ * Definitions of the bits in an Internet address integer.
+ * On subnets, host and network parts are found according
+ * to the subnet mask, not these masks.
+ */
+#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0)
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSA_NSHIFT 24
+#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
+#define IN_CLASSA_MAX 128
+
+#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000)
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSB_NSHIFT 16
+#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
+#define IN_CLASSB_MAX 65536
+
+#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000)
+#define IN_CLASSC_NET 0xffffff00
+#define IN_CLASSC_NSHIFT 8
+#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
+
+#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
+#define IN_MULTICAST(a) IN_CLASSD(a)
+#define IN_MULTICAST_NET 0xF0000000
+
+#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
+#define IN_BADCLASS(a) IN_EXPERIMENTAL((a))
+
+/* Address to accept any incoming messages. */
+#define INADDR_ANY ((unsigned long int) 0x00000000)
+
+/* Address to send to all hosts. */
+#define INADDR_BROADCAST ((unsigned long int) 0xffffffff)
+
+/* Address indicating an error return. */
+#define INADDR_NONE ((unsigned long int) 0xffffffff)
+
+/* Network number for local host loopback. */
+#define IN_LOOPBACKNET 127
+
+/* Address to loopback in software to local host. */
+#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */
+#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
+
+/* Defines for Multicast INADDR */
+#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */
+#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */
+#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */
+#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */
+
+
+/* <asm/byteorder.h> contains the htonl type stuff.. */
+#include <asm/byteorder.h>
+
+#ifdef __KERNEL__
+/* Some random defines to make it easier in the kernel.. */
+#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
+#define MULTICAST(x) (((x) & htonl(0xf0000000)) == htonl(0xe0000000))
+#define BADCLASS(x) (((x) & htonl(0xf0000000)) == htonl(0xf0000000))
+#define ZERONET(x) (((x) & htonl(0xff000000)) == htonl(0x00000000))
+#define LOCAL_MCAST(x) (((x) & htonl(0xFFFFFF00)) == htonl(0xE0000000))
+
+#endif
+
+#endif /* _LINUX_IN_H */
#include <linux/mm.h>
//#include <linux/highmem.h>
+// vif special values.
+#define VIF_PHYSICAL_INTERFACE -1
+#define VIF_UNKNOWN_INTERFACE -2
+#define VIF_DROP -3
+#define VIF_ANY_INTERFACE -4
+
#define HAVE_ALLOC_SKB /* For the drivers to know */
#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
#define SLAB_SKB /* Slabified skbuffs */
unsigned char *end; /* End pointer */
void (*destructor)(struct sk_buff *); /* Destruct function */
+
+ int src_vif; /* vif we came from */
+ int dst_vif; /* vif we are bound for */
+
+
+
#ifdef CONFIG_NETFILTER
/* Can be used for communication between hooks. */
unsigned long nfmark;
net_ring_t *net_ring;
int id;
struct sk_buff_head skb_list;
+ unsigned int domain;
// rules table goes here in next revision.
} net_vif_t;
extern net_vif_t *sys_vif_list[];
/* vif prototypes */
-net_ring_t *create_net_vif(int domain);
+net_vif_t *create_net_vif(int domain);
void destroy_net_vif(struct task_struct *p);
-
+void add_default_net_rule(int vif_id, u32 ipaddr);
+int net_get_target_vif(struct sk_buff *skb);
+void add_default_net_rule(int vif_id, u32 ipaddr);
unsigned long cpu_mask;
#endif
struct task_struct *p;
- unsigned int dest_dom;
+// unsigned int dest_dom;
int this_cpu = smp_processor_id();
struct softnet_data *queue;
unsigned long flags;
local_irq_save(flags);
netdev_rx_stat[this_cpu].total++;
-
+/*
skb->h.raw = skb->nh.raw = skb->data;
if ( skb->len < 2 ) goto drop;
while ( (p = p->next_task) != &idle0_task );
read_unlock(&tasklist_lock);
goto drop;
+*/
+ if (skb->src_vif == VIF_UNKNOWN_INTERFACE)
+ skb->src_vif = VIF_PHYSICAL_INTERFACE;
+
+ if (skb->dst_vif == VIF_UNKNOWN_INTERFACE)
+ net_get_target_vif(skb);
+if (skb->dst_vif > 1)
+printk("netifrx got packet bound for system vif %d.\n", skb->dst_vif);
+ if (sys_vif_list[skb->dst_vif] == NULL)
+ {
+ // the target vif does not exist.
+ goto drop;
+ }
- found:
+ if ( skb->dst_vif >= VIF_PHYSICAL_INTERFACE )
+ {
+ read_lock(&tasklist_lock);
+ p = &idle0_task;
+ do {
+ if ( p->domain != sys_vif_list[skb->dst_vif]->domain ) continue;
+ skb_queue_tail(&sys_vif_list[skb->dst_vif]->skb_list, skb);
+ cpu_mask = mark_hyp_event(p, _HYP_EVENT_NET_RX);
+ read_unlock(&tasklist_lock);
+ goto found;
+ }
+ while ( (p = p->next_task) != &idle0_task );
+ read_unlock(&tasklist_lock);
+ goto drop;
+ }
+// found:
#if 0
__skb_queue_tail(&queue->input_pkt_queue,skb);
/* Runs from irqs or BH's, no need to wake BH */
local_irq_restore(flags);
get_sample_stats(this_cpu);
return softnet_data[this_cpu].cng_level;
-#else
+//#else
hyp_event_notify(cpu_mask);
local_irq_restore(flags);
return 0;
kfree_skb(skb);
return NET_RX_DROP;
+
+found:
+ hyp_event_notify(cpu_mask);
+ local_irq_restore(flags);
+ return 0;
}
/* Deliver skb to an old protocol, which is not threaded well
unsigned int i, nvif;
rx_entry_t rx;
+ /* I have changed this to batch flush all vifs for a guest
+ * at once, whenever this is called. Since the guest is about to be
+ * scheduled and issued an RX interrupt for one nic, it might as well
+ * receive all pending traffic although it will still only get
+ * interrupts about rings that pass the event marker.
+ *
+ * If this doesn't make sense, _HYP_EVENT_NET_RX can be modified to
+ * represent individual interrups as _EVENT_NET_RX and the outer for
+ * loop can be replaced with a translation to the specific NET
+ * interrupt to serve. --akw
+ */
+
clear_bit(_HYP_EVENT_NET_RX, ¤t->hyp_events);
for (nvif = 0; nvif < current->num_net_vifs; nvif++)
while ( (skb = skb_dequeue(¤t->net_vif_list[nvif]->skb_list))
!= NULL )
{
+if (nvif > 0)
+printk("flushrxqueue on vif %d (sys: %d) (pkt_type=%d)\n", nvif, current->net_vif_list[nvif]->id, skb->pkt_type);
/*
* Write the virtual MAC address into the destination field
* of the ethernet packet. Furthermore, do the same for ARP
* reply packets. This is easy because the virtual MAC address
* is always 00-00-00-00-00-00.
+ *
+ * Actually, the MAC address is now all zeros, except for the
+ * first sixteen bits, which are the per-host vif id.
+ * (so eth0 should be 00-00-..., eth1 is 01-00-...)
*/
memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN);
+ *(unsigned int *)(skb->mac.ethernet->h_dest) = nvif;
if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
+ {
memset(skb->nh.raw + 18, 0, ETH_ALEN);
+ *(unsigned int *)(skb->nh.raw + 18) = nvif;
+ }
i = net_ring->rx_cons;
if ( i != net_ring->rx_prod )
}
net_ring->rx_cons = (i+1) & (RX_RING_SIZE-1);
if ( net_ring->rx_cons == net_ring->rx_event )
- set_bit(_EVENT_NET_RX, &s->events);
+ set_bit(_EVENT_NET_RX_FOR_VIF(nvif), &s->events);
}
kfree_skb(skb);
}
{
shared_info_t *shared = current->shared_info;
net_ring_t *net_ring = current->net_ring_base;
+ net_vif_t *current_vif;
unsigned int i, j;
struct sk_buff *skb;
tx_entry_t tx;
for ( j = 0; j < current->num_net_vifs; j++)
{
- net_ring = current->net_vif_list[j]->net_ring;
+ current_vif = current->net_vif_list[j];
+ net_ring = current_vif->net_ring;
for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) )
{
+if (j > 0)
+printk("net_update called with packet on vif %d system: %d)\n", j, current_vif->id);
if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
continue;
if ( TX_RING_INC(i) == net_ring->tx_event )
- set_bit(_EVENT_NET_TX, &shared->events);
+ set_bit(_EVENT_NET_TX_FOR_VIF(j), &shared->events);
skb = alloc_skb(tx.size, GFP_KERNEL);
if ( skb == NULL ) continue;
{
skb_get(skb); /* get a reference for non-local delivery */
skb->protocol = eth_type_trans(skb, skb->dev);
+ skb->src_vif = current_vif->id;
+ net_get_target_vif(skb);
+ if ( skb->dst_vif > VIF_PHYSICAL_INTERFACE )
+ {
+if (j > 0)
+ printk("Sent to netif_rx.\n");
+ if (netif_rx(skb) == 0)
+ /* Give up non-local reference. Packet delivered locally. */
+ kfree_skb(skb);
+ }
+ else if ( skb->dst_vif == VIF_PHYSICAL_INTERFACE )
+ {
+if (j > 0)
+ printk("Sent to physical device.\n");
+
+ skb_push(skb, skb->dev->hard_header_len);
+ dev_queue_xmit(skb);
+ }
+ else
+ {
+if (j > 0)
+ printk("dropped.\n");
+ kfree_skb(skb);
+ }
+
+ /*
+ skb_get(skb);
+ skb->protocol = eth_type_trans(skb, skb->dev);
if ( netif_rx(skb) == 0 )
{
- /* Give up non-local reference. Packet delivered locally. */
kfree_skb(skb);
}
else
{
- /* Pass the non-local reference to the net device. */
skb_push(skb, skb->dev->hard_header_len);
dev_queue_xmit(skb);
}
+ */
}
}
net_ring->tx_cons = i;
skb->len = 0;
skb->cloned = 0;
skb->data_len = 0;
+ skb->src_vif = VIF_UNKNOWN_INTERFACE;
+ skb->dst_vif = VIF_UNKNOWN_INTERFACE;
atomic_set(&skb->users, 1);
atomic_set(&(skb_shinfo(skb)->dataref), 1);
/* Helpers, implemented at the bottom. */
u32 getipaddr(const char *buff, unsigned int len);
u16 antous(const char *buff, int len);
+int anton(const char *buff, int len);
static int vfr_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
if (strncmp(&buffer[fs], "srcaddr", fl) == 0)
{
- op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl-1);
+ op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "dstaddr", fl) == 0)
{
- op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl-1);
+ op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "srcaddrmask", fl) == 0)
{
- op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl-1);
+ op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "dstaddrmask", fl) == 0)
{
- op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl-1);
+ op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "srcport", fl) == 0)
{
- op.u.net_rule.src_port = antous(&buffer[ts], tl-1);
+ op.u.net_rule.src_port = antous(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "dstport", fl) == 0)
{
- op.u.net_rule.dst_port = antous(&buffer[ts], tl-1);
+ op.u.net_rule.dst_port = antous(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "srcportmask", fl) == 0)
{
- op.u.net_rule.src_port_mask = antous(&buffer[ts], tl-1);
+ op.u.net_rule.src_port_mask = antous(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "dstportmask", fl) == 0)
{
- op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl-1);
+ op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "srcint", fl) == 0)
{
- op.u.net_rule.src_interface = antous(&buffer[ts], tl-1);
+ op.u.net_rule.src_interface = anton(&buffer[ts], tl);
}
else if (strncmp(&buffer[fs], "dstint", fl) == 0)
{
- op.u.net_rule.dst_interface = antous(&buffer[ts], tl-1);
+ op.u.net_rule.dst_interface = anton(&buffer[ts], tl);
}
else if ( (strncmp(&buffer[fs], "proto", fl) == 0))
{
- if (strncmp(&buffer[ts], "ip", tl))
+ if (strncmp(&buffer[ts], "any", tl) == 0)
+ op.u.net_rule.proto = NETWORK_PROTO_ANY;
+ if (strncmp(&buffer[ts], "ip", tl) == 0)
op.u.net_rule.proto = NETWORK_PROTO_IP;
- if (strncmp(&buffer[ts], "tcp", tl))
+ if (strncmp(&buffer[ts], "tcp", tl) == 0)
op.u.net_rule.proto = NETWORK_PROTO_TCP;
- if (strncmp(&buffer[ts], "udp", tl))
+ if (strncmp(&buffer[ts], "udp", tl) == 0)
op.u.net_rule.proto = NETWORK_PROTO_UDP;
- if (strncmp(&buffer[ts], "arp", tl))
+ if (strncmp(&buffer[ts], "arp", tl) == 0)
op.u.net_rule.proto = NETWORK_PROTO_ARP;
}
/* Helper functions start here: */
+int anton(const char *buff, int len)
+{
+ int ret;
+ char c;
+ int sign = 1;
+
+ ret = 0;
+
+ if (len == 0) return 0;
+ if (*buff == '-') { sign = -1; buff++; len--; }
+
+ while ( (len) && ((c = *buff) >= '0') && (c <= '9') )
+ {
+ ret *= 10;
+ ret += c - '0';
+ buff++; len--;
+ }
+
+ ret *= sign;
+ return ret;
+}
+
u16 antous(const char *buff, int len)
{
- int ret;
+ u16 ret;
char c;
ret = 0;
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/ip.h> //remove this.
#include <net/sock.h>
#define NET_TX_IRQ _EVENT_NET_TX
#define NET_RX_IRQ _EVENT_NET_RX
+#define NET_TX_IRQ_FOR_VIF(x) _EVENT_NET_TX_FOR_VIF(x)
+#define NET_RX_IRQ_FOR_VIF(x) _EVENT_NET_RX_FOR_VIF(x)
+
#define TX_MAX_ENTRIES (TX_RING_SIZE - 2)
#define RX_MAX_ENTRIES (RX_RING_SIZE - 2)
unsigned int rx_idx, tx_idx, tx_full;
net_ring_t *net_ring;
spinlock_t tx_lock;
+ unsigned int id;
};
{
struct net_private *np = dev->priv;
int error;
-
+ char *rxlabel, *txlabel;
+
+ // This is inevitably not the right way to allocate a couple of static strings.
+ rxlabel = kmalloc(sizeof("net-rx- "), GFP_KERNEL);
+ txlabel = kmalloc(sizeof("net-tx- "), GFP_KERNEL);
+ if ((rxlabel == NULL) || (txlabel == NULL)) goto fail;
+ sprintf(rxlabel, "net-rx-%d", np->id);
+ sprintf(txlabel, "net-tx-%d", np->id);
+
np->rx_idx = np->tx_idx = np->tx_full = 0;
memset(&np->stats, 0, sizeof(np->stats));
network_alloc_rx_buffers(dev);
- error = request_irq(NET_RX_IRQ, network_rx_int, 0, "net-rx", dev);
+ error = request_irq(NET_RX_IRQ_FOR_VIF(np->id), network_rx_int, 0,
+ rxlabel, dev);
if ( error )
{
printk(KERN_WARNING "%s: Could not allocate receive interrupt\n",
goto fail;
}
- error = request_irq(NET_TX_IRQ, network_tx_int, 0, "net-tx", dev);
+ error = request_irq(NET_TX_IRQ_FOR_VIF(np->id), network_tx_int, 0,
+ txlabel, dev);
if ( error )
{
printk(KERN_WARNING "%s: Could not allocate transmit interrupt\n",
dev->name);
- free_irq(NET_RX_IRQ, dev);
+ free_irq(NET_RX_IRQ_FOR_VIF(np->id), dev);
goto fail;
}
return 0;
fail:
+ if ( rxlabel ) kfree(rxlabel);
+ if ( txlabel ) kfree(txlabel);
if ( np->net_ring->rx_ring ) kfree(np->net_ring->rx_ring);
if ( np->net_ring->tx_ring ) kfree(np->net_ring->tx_ring);
if ( np->rx_skb_ring ) kfree(np->rx_skb_ring);
{
unsigned int i;
struct net_private *np = (struct net_private *)dev->priv;
-
+
+if ((np->id > 0) || ((skb->len > 20)
+ && (skb->nh.iph != NULL)
+ && (skb->nh.iph->protocol == 1)))
+ printk(KERN_WARNING "TX on vif %d (dev:%p)\n", np->id, dev);
+
if ( np->tx_full )
{
printk(KERN_WARNING "%s: full queue wasn't stopped!\n", dev->name);
skb->protocol = eth_type_trans(skb, dev);
np->stats.rx_packets++;
np->stats.rx_bytes += np->net_ring->rx_ring[i].size;
+
+if (((skb->len > 20)
+ && ((*(unsigned char *)(skb->data + 9) == 1) || (np->id > 0)) ))
+ printk(KERN_WARNING "RX on vif %d (dev:%p)\n", np->id, dev);
+if ((skb != NULL) && (skb->data != NULL) && (skb->len > 20) && ntohl(*(unsigned long *)(skb->data + 16)) == 167903489)
+ printk(KERN_WARNING "RX INT (driver): pkt_type is %d.!", skb->pkt_type);
+
netif_rx(skb);
dev->last_rx = jiffies;
+
+
}
np->rx_idx = i;
/* Deal with hypervisor racing our resetting of rx_event. */
smp_mb();
- if ( np->net_ring->rx_cons != i ) goto again;
+ if ( np->net_ring->rx_cons != i ) {
+//printk("redoing network rx...\n");
+ goto again;
+ }
}
}
-static int network_close(struct net_device *dev)
+int network_close(struct net_device *dev)
{
struct net_private *np = dev->priv;
netif_stop_queue(dev);
- free_irq(NET_RX_IRQ, dev);
- free_irq(NET_TX_IRQ, dev);
+ free_irq(NET_RX_IRQ_FOR_VIF(np->id), dev);
+ free_irq(NET_TX_IRQ_FOR_VIF(np->id), dev);
network_free_rx_buffers(dev);
kfree(np->net_ring->rx_ring);
kfree(np->net_ring->tx_ring);
}
-static int __init init_module(void)
+int __init init_module(void)
{
int i, err;
struct net_device *dev;
dev->stop = network_close;
dev->get_stats = network_get_stats;
+ memset(dev->dev_addr, 0, ETH_ALEN);
+ *(unsigned int *)(dev->dev_addr) = i;
+
if ( (err = register_netdev(dev)) != 0 )
{
kfree(dev);
}
np->dev = dev;
+ np->id = i;
list_add(&np->list, &dev_list);
+printk(KERN_WARNING "Added VIF, ifindex is %d.\n", dev->ifindex);
}
return 0;
return ret;
}
+/* Event message note:
+ *
+ * Here, as in the interrupts to the guestos, additional network interfaces
+ * are defined. These definitions server as placeholders for the event bits,
+ * however, in the code these events will allways be referred to as shifted
+ * offsets from the base NET events.
+ */
+
/* Events that a guest OS may receive from the hypervisor. */
-#define EVENT_NET_TX 0x01 /* packets for transmission. */
-#define EVENT_NET_RX 0x02 /* empty buffers for receive. */
-#define EVENT_TIMER 0x04 /* a timeout has been updated. */
-#define EVENT_DIE 0x08 /* OS is about to be killed. Clean up please! */
-#define EVENT_BLK_TX 0x10 /* packets for transmission. */
-#define EVENT_BLK_RX 0x20 /* empty buffers for receive. */
+#define EVENT_BLK_TX 0x01 /* packets for transmission. */
+#define EVENT_BLK_RX 0x02 /* empty buffers for receive. */
+#define EVENT_TIMER 0x04 /* a timeout has been updated. */
+#define EVENT_DIE 0x08 /* OS is about to be killed. Clean up please! */
+#define EVENT_NET_TX 0x10 /* packets for transmission. */
+#define EVENT_NET_RX 0x20 /* empty buffers for receive. */
+#define EVENT_NET2_TX 0x40 /* packets for transmission. */
+#define EVENT_NET2_RX 0x80 /* empty buffers for receive. */
+
+/* should these macros and the ones below test for range violation? */
+#define EVENT_NET_TX_FOR_VIF(x) (EVENT_NET_TX << (2 * x))
+#define EVENT_NET_RX_FOR_VIF(x) (EVENT_NET_RX << (2 * x))
+
/* Bit offsets, as opposed to the above masks. */
-#define _EVENT_NET_TX 0
-#define _EVENT_NET_RX 1
-#define _EVENT_TIMER 2
-#define _EVENT_DIE 3
-#define _EVENT_BLK_TX 4
-#define _EVENT_BLK_RX 5
+#define _EVENT_BLK_TX 0
+#define _EVENT_BLK_RX 1
+#define _EVENT_TIMER 2
+#define _EVENT_DIE 3
+#define _EVENT_NET_TX 4
+#define _EVENT_NET_RX 5
+#define _EVENT_NET2_TX 6
+#define _EVENT_NET2_RX 7
+
+#define _EVENT_NET_TX_FOR_VIF(x) (_EVENT_NET_TX + (2 * x))
+#define _EVENT_NET_RX_FOR_VIF(x) (_EVENT_NET_RX + (2 * x))
/*
* NB. We expect that this struct is smaller than a page.
int num_net_rings;
blk_ring_t *blk_ring; /* block io communication rings */
unsigned char cmd_line[1]; /* variable-length */
+ unsigned long frame_table; /* mapping of the frame_table for dom0 */
} start_info_t;
/* For use in guest OSes. */
} net_ring_t;
/* Specify base of per-domain array. Get returned free slot in the array. */
-net_ring_t *create_net_vif(int domain);
+//net_ring_t *create_net_vif(int domain);
/* Packet routing/filtering code follows:
*/
#define NETWORK_ACTION_ACCEPT 0
#define NETWORK_ACTION_COUNT 1
-#define NETWORK_PROTO_IP 0
-#define NETWORK_PROTO_TCP 1
-#define NETWORK_PROTO_UDP 2
-#define NETWORK_PROTO_ARP 3
+#define NETWORK_PROTO_ANY 0
+#define NETWORK_PROTO_IP 1
+#define NETWORK_PROTO_TCP 2
+#define NETWORK_PROTO_UDP 3
+#define NETWORK_PROTO_ARP 4
typedef struct net_rule_st
{
u16 dst_port_mask;
u16 proto;
- u16 src_interface;
- u16 dst_interface;
+ int src_interface;
+ int dst_interface;
u16 action;
} net_rule_t;
#define NET_TX_IRQ _EVENT_NET_TX
#define NET_RX_IRQ _EVENT_NET_RX
+#define NET2_TX_IRQ _EVENT_NET2_TX
+#define NET2_RX_IRQ _EVENT_NET2_RX
#define TIMER_IRQ _EVENT_TIMER
#define NR_IRQS (sizeof(HYPERVISOR_shared_info->events) * 8)